
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
import org.coolsofteware.profiling.analysisfw.MainController;
import org.coolsoftware.emftext.json.resource.json.mopp.JsonResource;
import org.coolsoftware.profiling.workbench.analysis.ctrl.CPUAnalyserController;
import org.coolsoftware.profiling.workbench.analysis.ctrl.DiskAnalyserController;
import org.coolsoftware.profiling.workbench.analysis.ctrl.NetworkAnalyserController;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

public class AutoControl {

//	String propertyFilePath = "/home/L/workspace/eclipse/SHK/CoolSW/org.coolsoftware.profiling.examples.sorting/config.properties";
	// running program use this name
	public String programName;
	// path of eureqa server
	public String eureqaServerPath;
	// path of eureqa client
	public String eureqaClientPath;
	// path for the related btrace, systemtap, json files
	public String btracePath;
	public String stapPath;
	public String jsonPath;
	// json analyze Type: 1-> cpu, 2-> disk 3-> network
		public int jsonTyp;
	// path of exported files for the eureqa
	public String exportfilePath;
	// eureqa search option
	public String searchOpt;
	// eureqa search fitness
	public String searchFit;
	// eureqa search loop number
	public String loopNr;

	Properties prop = new Properties();

	public AutoControl() {

		try {
//			prop.load(new FileInputStream(propertyFilePath));
			prop.load(this.getClass().getResourceAsStream("config.properties"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		initProp();
	}

	/**
	 * initial configuration parameters.
	 */
	public void initProp() {
		programName = prop.getProperty("programName");
		// path of eureqa server
		eureqaServerPath = prop.getProperty("eureqaServerPath");
		// path of eureqa client
		eureqaClientPath = prop.getProperty("eureqaClientPath");
		// path for the related btrace, systemtap, json files
		btracePath = prop.getProperty("btracePath");
		stapPath = prop.getProperty("stapPath");
		jsonPath = prop.getProperty("jsonPath");
		// json analyze Type: 1-> cpu, 2-> disk 3-> network
				jsonTyp = Integer.parseInt(prop.getProperty("jsonTyp"));
		// path of exported files for the eureqa
		exportfilePath = prop.getProperty("exportfilePath");
		// eureqa search option
		searchOpt = prop.getProperty("searchOpt");
		// eureqa search fitness
		searchFit = prop.getProperty("searchFit");
		// eureqa search loop number
		loopNr = prop.getProperty("loopNr");
	}

	/**
	 * get the thread number with the process name.
	 */
	public String getThreadNr() {

		String threadNr = "-1";
		try {
			ProcessBuilder pb = new ProcessBuilder("jps");
			Process process = pb.start();
			BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
					process.getInputStream()));
			String l = null;
			while ((l = myBuffer.readLine()) != null) {
				if (l.endsWith(programName)) {
					threadNr = l.substring(0, l.length() - programName.length()
							- 1);
					System.out
							.println("the thread number of java function is: "
									+ threadNr);
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return threadNr;
	}

	/**
	 * run the Btrace with the thread number.
	 * 
	 * @param threadNr
	 *            running thread number.
	 */
	public void runBtrace(String threadNr) {

		try {
			ProcessBuilder pb = new ProcessBuilder("btrace", threadNr,
					btracePath);
			System.out.println("Btrace running!");
			Process process = pb.start();
			// printError(process);
			// printInput(process);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * run the stap with the thread number.
	 * 
	 * @param threadNr
	 * @return stap process number
	 */
	public String runStap(String threadNr) {
		Process process = null;
		String stapThrNr = "-1";
		try {
			ProcessBuilder pb = new ProcessBuilder("stap", stapPath, "-F",
					"-o", jsonPath, "-x", threadNr, "-v");
			// ProcessBuilder pb = new ProcessBuilder("stap", stapPath,"-x",
			// threadNr, "-v");
			System.out.println("systemTap running!");
			process = pb.start();
			// printError(process);
			stapThrNr = printInput(process);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return stapThrNr;
	}

	/**
	 * kill the systemTap process.
	 * 
	 * @param stapThrNr
	 *            process number of systemTap.
	 */
	public void killStap(String stapThrNr) {
		ProcessBuilder pb = new ProcessBuilder("kill", "-s", "SIGTERM",
				stapThrNr);
		try {
			pb.start();
			System.out.println("systemTap is killed!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * wait till finish analyzing json file.
	 * 
	 * @throws IOException
	 */
	public void analyzeJson() {

		System.out.println("now analyze the json file.");
		// analyze json file
		ResourceSet rs = new ResourceSetImpl();
		Resource resource = rs.getResource(URI.createFileURI(jsonPath), true);
		if (resource instanceof JsonResource) {
			JsonResource jres = (JsonResource) resource;
			MainController.INSTANCE.loadModel(jres);
		}

		switch (jsonTyp) {
		case 1:
			// merge the data
			CPUAnalyserController.INSTANCE.mergeEquivalentMethodExecutions();
			// export the data from json file
			try {
				CPUAnalyserController.INSTANCE
						.exportCpuDataForEureqa(exportfilePath);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			break;
		case 2:
			// merge the data
			DiskAnalyserController.INSTANCE.mergeEquivalentMethodExecutions();
			// export the data from json file
			try {
				DiskAnalyserController.INSTANCE
						.exportDiskDataForEureqa(exportfilePath);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			break;
		case 3:
			// merge the data
			NetworkAnalyserController.INSTANCE
					.mergeEquivalentMethodExecutions();
			// export the data from json file
			try {
				NetworkAnalyserController.INSTANCE
						.exportNetworkDataForEureqa(exportfilePath);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			break;
		default:
			System.out.println("the selected type is not in the list!");
		}
	}

	/**
	 * run the eureqa Server.
	 */
	public void runEureqaServer() {
		try {
			new ProcessBuilder(eureqaServerPath).start();
			System.out.println("eureqaServer running!");
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}

	/**
	 * kill the eureqa server process.
	 */
	public void killEureqaServer() {
		try {
			new ProcessBuilder("pkill", "eureqa_server").start();
			System.out.println("eureqaServer is killed!");
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}

	/**
	 * run the eureqa Client.
	 */
	public void runEureqaClinet() {
		try {
			Process cleintProcess = new ProcessBuilder(eureqaClientPath,
					exportfilePath, searchOpt, searchFit, loopNr).start();
			System.out.println("eureqaClient running!");
			printInput(cleintProcess);
		} catch (Exception e) {
			System.out.println("Error exec!");
		}
	}

	/**
	 * wait n seconds.
	 * 
	 * @param sec
	 *            second
	 */
	public void wait(int sec) {
		try {
			Thread.sleep(sec * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * print error.
	 * 
	 * @param process
	 *            process for btrace/stap/eureqa
	 */
	public void printError(Process process) {
		BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
				process.getErrorStream()));
		String l = null;
		try {
			while ((l = myBuffer.readLine()) != null) {
				System.out.println(l);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * print input message.
	 * 
	 * @param process
	 *            process for btrace/stap/eureqa
	 * 
	 * @return the last line of print
	 */
	public String printInput(Process process) {
		BufferedReader myBuffer = new BufferedReader(new InputStreamReader(
				process.getInputStream()));
		String lastline = "";
		String l = null;
		try {
			while ((l = myBuffer.readLine()) != null) {
				System.out.println(l);
				lastline = l;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return lastline;
	}
}